// class 类型版本
class Primise {
    constructor(executor) {
        // 默认值
        this.PromiseState = 'pending'
        this.PromiseResult = null
        // 声明属性
        this.callbacks = []
        const _this = this
        //resolve 函数
        function resolve(data){
            // 让状态只改变一次
            if (_this.PromiseState !== 'pending') return
            _this.PromiseState = 'fulfilled'
            _this.PromiseResult = data
            // 调用成功的回调函数
            _this.callbacks.forEach(item => {
                item.onResolved(data)
            })
        }
        //reject 函数
        function reject(data){
            // 让状态只改变一次
            if (_this.PromiseState !== 'pending') return
            _this.PromiseState = 'rejected'
            _this.PromiseResult = data
            // 执行回调
            _this.callbacks.forEach(item => {
                item.onRejected(data)
            })
        }

        //同步调用『执行器函数』
        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error)
        }
    }

    then(onResolved, onRejected) {
        const _this = this
        // 判断失败回调函数参数
        if (typeof onResolved !== 'function') {
            onResolved = value => value
        }
        // 判断失败回调函数参数
        if (typeof onRejected !== 'function') {
            onRejected = reason => {
                throw reason
            }
        }
        return new Promise((resolve, reject) => {
            function callback(type) {
                try {
                    // 获取回调函数的执行结果
                    let result = type(_this.PromiseResult)
                    if (result instanceof Promise) {
                        result.then(value => {
                            resolve(value)
                        }, reason => {
                            reject(reason)
                        })
                    } else {
                        // 如果不是promise类型，则返回状态改为promise成功类型
                        resolve(result)
                    }
                } catch (error) {
                    reject(error)
                }
            }
            //调用回调函数  PromiseState
            if (this.PromiseState === 'fulfilled') {
                setTimeout(() => {
                    callback(onResolved)
                })
            }
            if (this.PromiseState === 'rejected') {
                setTimeout(() => {
                    callback(onRejected)
                })
            }
            if (this.PromiseState === 'pending') {
                this.callbacks.push({
                    onResolved: function() {
                        callback(onResolved)
                    },
                    onRejected: function() {
                        callback(onRejected)
                    }
                })
            }
        })    
    }

    catch(onRejected) {
        return this.then(undefined, onRejected)
    }

    static resolve(value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(value => {
                    resolve(value)
                }, reason => {
                    reject(reason)
                })
            } else {
                resolve(value)
            }
        })
    }

    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }
    
    static all(prommises) {
        return new Promise((resolve, reject) => {
            // 计数
            let count = 0
            // 把每一项保存到数组中
            let arr = []
            for (let i = 0; i < prommises.length; i++) {
                prommises[i].then(value => {
                    count++
                    arr[i] = value
                    // 判断是否都为成功 promise
                    if (count === prommises.length) {
                        // 都为成功则放回全部成功的 promise
                        resolve(arr)
                    }
                }, reason => {
                    reject(reason)
                })
            }
        })
    }

    static race(prommises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < prommises.length; i++) {
                prommises[i].then(value => {
                    resolve(value)
                }, reason => {
                    reject(reason)
                })
            }
        })
    }
}